package edu.gatech.mobile.scene.ui;

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.DataInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.FileWriter;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.util.List;

import org.opencv.android.BaseLoaderCallback;
import org.opencv.android.LoaderCallbackInterface;
import org.opencv.android.OpenCVLoader;

import android.app.Activity;
import android.content.Intent;
import android.graphics.Point;
import android.location.Location;
import android.location.LocationManager;
import android.os.Bundle;
import android.os.Environment;
import android.util.Log;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.Toast;
import edu.gatech.mobile.scene.AppConstants;
import edu.gatech.mobile.scene.R;
import edu.gatech.mobile.scene.image.util.MatUtil;
import edu.gatech.mobile.scene.model.ImageInfo;
import edu.gatech.mobile.scene.provider.impl.ImageInfoDBImpl;
import edu.gatech.mobile.scene.ui.camera.CaptureActivity;
import edu.gatech.mobile.scene.ui.manage.ManageImageActivity;

/***
 * Home of the app. Loads all of hte training data.
 * @author Jing
 *
 */
public class DataLoadingActivity extends Activity implements OnClickListener{
	
	private static final String TAG = DataLoadingActivity.class.getSimpleName();
	private static boolean dataLoaded = false;
	
	/**
	 * initialize opencv for application use.
	 */
	private BaseLoaderCallback mOpenCVCallBack = new BaseLoaderCallback(this) {
		@Override
		public void onManagerConnected(int status) {
			switch (status) {
			case LoaderCallbackInterface.SUCCESS:
				Log.i(TAG, "OpenCV loaded successfully");
				initApplicatoniContext();
				break;
			default:
				super.onManagerConnected(status);
				break;
			}
		}
	};
	
	@Override
	public void onCreate(Bundle icicle) {
		super.onCreate(icicle);
		if (!OpenCVLoader.initAsync(OpenCVLoader.OPENCV_VERSION_2_4_2, this,
				mOpenCVCallBack)) {
			Log.e(TAG, "Cannot connect to OpenCV Manager");
		}
	}
	
	/**
	 * Load  all the training data. If everything is loaded successfully, then populate the UI components.
	 */
	private void initApplicatoniContext() {
		if(MatUtil.initializeApplicationContext(this)){
			Toast.makeText(this, "Data loaded", Toast.LENGTH_LONG).show();
			setContentView(R.layout.activity_main);
			((Button)findViewById(R.id.new_image)).setOnClickListener(this);
			((Button)findViewById(R.id.manage_image)).setOnClickListener(this);
			((Button)findViewById(R.id.back_db)).setOnClickListener(this);
		}
	}
	
	/**
	 * Click listener that handles all of the buttons of this activity
	 */
	@Override
	public void onClick(View v) {
		Intent i = null;
		switch (v.getId()) {
		
		//Taking a new image
		case R.id.new_image:
			i = new Intent(this, CaptureActivity.class);
			startActivity(i);
			break;
		
		//manage existing image
		case R.id.manage_image:
			i = new Intent(this, ManageImageActivity.class);  
			startActivity(i);
			break;
		
		//For saving existing data onto the sdcard
		case R.id.back_db:
//			try {
//				backupDb();
//			} catch (IOException e) {
//				// TODO Auto-generated catch block
//				e.printStackTrace();
//			}
			
			//getPreLoadedData();  
			break;
		default:
			break;
		}
		
	}
	
	
	/**
	 * Load in data in the csv file.
	 */
	private void getPreLoadedData(){
		ImageInfoDBImpl imageDB = new ImageInfoDBImpl(this);
		File sdCard = Environment.getExternalStorageDirectory();
		File myImages = new File(sdCard + "/"+AppConstants.IMG_FOLDER);
		FileInputStream fstream;
		try {
			fstream = new FileInputStream(myImages+"/exported_images/image_info.csv");
			// Get the object of DataInputStream
			DataInputStream in = new DataInputStream(fstream);
			BufferedReader br = new BufferedReader(new InputStreamReader(in));
			String strLine;
			while ((strLine = br.readLine()) != null) {
				String[] data = strLine.split(",");
				ImageInfo image = new ImageInfo();
				image.setImagePath(myImages+"/"+data[0]);
				Point lPoint = new Point (Integer.parseInt(data[3]), Integer.parseInt(data[4]));
				Point rPoint = new Point (Integer.parseInt(data[5]), Integer.parseInt(data[6]));
				Point[] horizonPoints = {lPoint, rPoint};
				image.setHorizonPoints(horizonPoints);
				Location loc = new Location(LocationManager.GPS_PROVIDER);
				loc.setLatitude(Double.parseDouble(data[1]));
				loc.setLongitude(Double.parseDouble(data[2]));
				image.setLocation(loc);
				float[] accelValues = {0,0,0};
				image.setAccelerometer(accelValues);
				image.setMagneticField(accelValues);
				image.setFocalLength(0);
				image.setWhiteBalance(0);
				imageDB.putImage(image);
			}
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}

	}
	
	
	
	/**
	 * Saving the database onto sdcard as .db files. Can be access with java sqlite driver later.
	 * @return
	 * @throws IOException
	 */
	 private String backupDb() throws IOException {
	        File sd = Environment.getExternalStorageDirectory();
	        //File data = Environment.getDataDirectory();

	        if (sd.canWrite()) {

	            String currentDBPath = "data/data/edu.gatech.mobile.scene/databases/image_understanding_db";
	            String backupDBPath = "/scene.db";
	            File currentDB = new File(currentDBPath);
	            File backupDB = new File(sd, backupDBPath);

	            if (backupDB.exists()) backupDB.delete();

	            if (currentDB.exists()) {
	                copy(currentDB, backupDB);
	            }

	           return backupDB.getAbsolutePath();
	       }
	        else{
	            return null;
	        }
	    }

	 	
	 /**
	  * Copy f1 to f2.
	  * @param f1 source file
	  * @param f2 destination file
	  */
	    private void copy(File f1, File f2) {
	       /* FileChannel src = null;
	        FileChannel dst = null;
	        try {
	            src = new FileInputStream(from).getChannel();
	            dst = new FileOutputStream(to).getChannel();
	            dst.transferFrom(src, 0, src.size());
	        }
	        finally {
	            if (src != null)
	                src.close();
	            if (dst != null)
	                dst.close();
	        }*/

	        try {
	            InputStream in = new FileInputStream(f1);

	            // For Append the file.
	            // OutputStream out = new FileOutputStream(f2,true);

	            // For Overwrite the file.
	            OutputStream out = new FileOutputStream(f2);

	            byte[] buf = new byte[1024];
	            int len;
	            while ((len = in.read(buf)) > 0) {
	                out.write(buf, 0, len);
	            }
	            in.close();
	            out.close();
	            System.out.println("File copied.");
	        } catch (FileNotFoundException ex) {
	            System.out
	                    .println(ex.getMessage() + " in the specified directory.");
	            System.exit(0);
	        } catch (IOException e) {
	            System.out.println(e.getMessage());
	        }
	    }
	
	 /**
	  * Export the database as .csv files, which can be moved to other devices
	  */
	private void exportData() {
		ImageInfoDBImpl imageDB = new ImageInfoDBImpl(this);
		String sdCard = Environment.getExternalStorageDirectory().getAbsolutePath();
		String filePath  = new File(sdCard + "/"+AppConstants.IMG_FOLDER).getAbsolutePath();
		String ouputCSVFile = filePath+"/export.csv";
		BufferedWriter output = null;
		try {
			output= new BufferedWriter(new FileWriter(ouputCSVFile, false));
		} catch (IOException e) {
			e.printStackTrace();
		}
		if(output!=null){
			StringBuilder sb = new StringBuilder();
			sb.append("image name,");
			sb.append("point1 x,");
			sb.append("point1 y,");
			sb.append("point2 x,");
			sb.append("point2 y");
			sb.append("\n");
			List<ImageInfo> images = imageDB.getAllImages(false);
			for(ImageInfo imageInfo : images){
				File f = new File(imageInfo.getFileName());
				sb.append(f.getName());
				sb.append(",");
				sb.append(imageInfo.getHorizonPoints()[0].x);
				sb.append(",");
				sb.append(imageInfo.getHorizonPoints()[0].y);
				sb.append(",");
				sb.append(imageInfo.getHorizonPoints()[1].x);
				sb.append(",");
				sb.append(imageInfo.getHorizonPoints()[1].y);
				sb.append("\n");
			}
			try {
				output.write(sb.toString());
				output.close();
				Toast.makeText(this, "Exported to sdcard. \n Check /gatech directory", Toast.LENGTH_LONG).show();
			} catch (IOException e) {
				e.printStackTrace();
				Toast.makeText(this, "Export failed", Toast.LENGTH_LONG).show();
			}
		}
		else{
			Toast.makeText(this, "Export failed", Toast.LENGTH_LONG).show();
		}
	}
}
